大家好!承前兩天,我們使用 Vite 建置了 Vue 專案,並且理解了它的資料夾結構,今天一起來更深入看一下這個專案是怎麼「組」起來的。
App.vue
中可以看到 SFC 的結構,由 <script setup></script>
、<template></template>
、<style></style>
組成。
繼續看看這些區塊都做了什麼事!
引入了 src/component
中的 HelloWorld
、TheWelcome
這兩個組件。
HelloWorld
被使用在 <div class="wrapper">
中的區塊。
我們到 HelloWorld.vue
裡看它做了什麼事:
<script setup></script>
中使用了以下語法:
<script setup>
defineProps({
msg: {
type: String,
required: true
}
})
</script>
defineProps
(Props 意為 property)中定義了:
msg: {}
:指定 msg
為組件的屬性。type: String
:定義 msg
屬性的類型為 String
。required: true
:msg 屬性是必須提供的。而 defineProps()
的作用是:告訴子組件要「接收哪些數據」,並且這些數據必須來自「父組件」。
所以,父組件 import 這個子組件時,必須提供一個「字符串型的 msg property」(不會報錯但會警告否則會報錯)。
因此!App.vue
根組件 import HelloWorld
的時候,要提供 defineProps
裡定義的東西。
而 <template></template>
定義了基本的組件 html 結構。
<template>
<div class="greetings">
<h1 class="green">{{ msg }}</h1>
<h3>
You’ve successfully created a project with
<a href="https://vitejs.dev/" target="_blank" rel="noopener">Vite</a> +
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
</h3>
</div>
</template>
它做了什麼事?
<h1 class="green">{{ msg }}</h1>
:這裡的 {{ msg }}
是 Vue 中的「文本插值」,代表當父組件傳遞一個 msg
的屬性時,它會在 <h1>
標籤中顯示內容 {{ msg }}
。
msg
」???回頭看一下 App.vue
做了什麼:
在 <HelloWorld />
定義了「屬性:msg」和「值:You did it」。
也就是剛剛提到的!子組件 HelloWorld
定義了 defineProps()
,所以這些數據會由父組件傳到 HelloWorld
中 {{ msg }}
處。
這是因為 Vue 中有「自定義標籤」的特性,當我們將組件 import 到某個檔案,相等於我們將該組件定義為一個變數,並且我們可以在該檔案中用該變數做事。
所以 import HelloWorld from './components/HelloWorld.vue'
讓我們可以在這邊用 HelloWorld
作為自定義標籤,並渲染 HelloWorld.vue
組件的內容。
TheWelcome
在 App.vue
中也是用了自定義標籤,目前看起來就是將 TheWelcome
這個組件的東東塞進來。
看一下 TheWelcome
裡面是什麼!
看起來也是許多的組件被 import 進來⋯⋯
我們可以從開發者工具端詳一下東西是怎麼塞?進去的(我看過我覺得挺有感覺 XDDD,有種拼積木的感覺)
這邊我們來看看 HelloWorld
這個組件。
在 App.vue
中使用 <HelloWorld />
時,會把 HelloWorld.vue
組件的內容插入到 App.vue
的結構,而這些內容會渲染為 App.vue
的一部分,有點像「填充」的過程~
因此,HelloWorld.vue
的 <div class="greetings"></div>
最終會填充到 App.vue
中 <div class="wrapper">
內的 <HelloWorld />
標籤所代表的地方。
不過據說 SFC 會經過 JS 編譯成為渲染函式,進而操作虛擬 DOM(這部分還沒有研究,先帶到這邊 QQ)
我自己覺得今天有比較理解 Vue 中組件相互的應用與關係,繼續繼續⋯⋯明天來看看 Vue 的模板語法(自我懷疑小裁判到目前都蠻沈默,繼續保持)
鐵人賽竟然已經完成 1/5 了!